Dein Genie 3s, die 5 unbekannten Wesen

Nun soll auch ein Z180-Prozessor Chef im System sein können

Helmut Bernhardt, Arnulf Sopp

Vorbemerkung: Im Folgenden ist viel von "wir"' die Rede. Dies aus Gründen der
Sprachökonomie. Jeder von uns machte aber in Wirklichkeit das, was er am
besten konnte: Helmut die Hardare. Arnulf die Software. Das  Pflichtenheft
für beides entstand unter Mitwirkung etlicher Gebinde Hopfenbrause.

Die Hardware

Vor längerer Zeit hatten wir unter ähnlichem Titel mal eine Erweiterung
für den Genie IIIs beschrieben (1), mit der sämtliche Speicher (User-RAM, Vi-
deo-RAM, HRG-RAM und Zeichengenerator-RAM) auf die vierfache Größe erweitert
werden konnten. Außerdem fiel dabei noch ein SRAM ab, das parallel zum
Boot-EPROM arbeitete. Dafür haben wir an den Sockel der Z80-CPU ein Adapter-Board
gesteckt, das den Z80 aufnahm und einen schreib- und lesbaren Port bereitstellte,
mit dessen Bits die Umschaltung dar Speicherbanks gesteuert wurde.

Über dieses primitive Banking kann z.B. ein Genie 2s-Anwender, der auf eine
HD64180-CPU umgerüstet hat (2), nur milde lächeln, wenn er seinen Computer
mit 9,2 MHz (gegenüher 7,2 MHz des G3s) fährt. Es galt, dieses Manko
beim G3s auszubügeln. Dafür haben wir ein neues Adapter-Board gebaut, auf
dem nun kein Z80 (auch kein HD64180), sonden ein Z180 steckt. Der Z180 hat
(wie auch der neuere HD64180-PLCC) 20 Adreßleitungen und kann damit über
seine MMU und die beiden DMA-Känle 1 Megabyte RAM direkt adressieren.

Um diese CPU so, wie sie gedacht ist, direkt zu nutzen, hätte das riesige
Betriebssystem G-DOS 2.3 (oder Calva-DOS 2.4, die auf 1 Megabyte angepaßte
Version) vollkommen auf HD64180-MMU-Banking umgeschrieben werden müssen.
In über 63 kB SYS- und anderen systemeigenen Files hatten alle OUT-befehle
an die System-Steuerports F9h und FAh gesucht und auf entsprechende
Z180-MMU-Befehle geändert werden müssen. Außer viel Arbeit hätte das auch
die Kompatibilität mit anderen Computern dieser und ähnhicher Bauart gekostet.
Da entschieden wir uns dafür, dem Calva-DOS sein Banking über die
Systemteuerports zunächst mal zu erhalten. Die Ports F9h, FAh und FBh (früher
F3h) auf dem Adapter-Board haben ihre volle Funktionsfähigkeit behalten.

Nun ist aber der Einsatz eines HD64180 bzw. Z180 witzlos, wenn dessen
MMU und DMAC nicht benutzt werden können. Wir haben beide Möglichkeiten
eingerichtet: Nach dem Einschalt-Reset sind alle Systemport-Bits auf 0
gesetzt und ein voll G3s-kopatibler Computer incl. Erweiterung auf vierfache
Speichergröße liegt vor. Durch Setzen des früher anders belegten Bits D6 in
Port FBh kann aber umgeschaltet werden in einen lupenreinen Z180-Computer:
alle Banking- und Common-Definitions-Bits der Systemports hahen dann keine
Fünktion mehr. Das RAM wird ausschließlich durch die Adreßleitungen der CPU
adressiert.

Nur das Einblenden von memory mapped I/O-Baugruppen in die dafür vorgesehenen
physikalischen Adreßbereiche erfolgt, wie im G3s-Modus, durch die
entsprechenden Systemport-Bits. Gleichwohl sind deren logische Adressen
variabel. Der G3s dekodiert bei ihrer Selektion nur die Adreßbits 0-1.
Wie der Z180 derzeit sein physikalisches Megabyte in bis zu drei logische
Adreßbereiche unterteilt, indem er mit  A12-A19 jongliert, da redet ihm der
G3s nicht drein.

Um die Ausmaße eines Adapter-Boards mit diesen Umschaltmöglichkeiten
(s. Foto) in Grenzen zu halten, mußten wir zwei PALs einsetzen. PAL 1 erzeugt
lediglich die Port-Freigabesignale /OUTFB und /INFB (und noch einige
weitere Freigabesignale - s. PAL-Listing), mit denen das Latch 74LS273 und
der Lesetreiber 74LS244 angesteuert werden, die den zusätzlichen Port BFh
realisieren.

Die eigentliche Steuerung der RAM-Adressierung leistet PAL 2. Durch die
Ausgänge /CAS0-/CAS3 wird eine der vier Reihen von 41256er RAM-Chips selektiert.
A16 und A17 wählen darin einen 64 kB-Block an. Für die Adressierung
im Z180-Modus gelangen die Adressen A16-A19 an das PAL. Im G3s-Modus erfolgt
das Banking durch die Bits D6 und D7 von Port F9h sowie D0 und D1 von Port
FBh. D7 von Port FBh entscheidet, ob bei logischer Adressierung im eingestellten
Common-Bereich (0000h-3FFFh oder E000h-FFFFh) nur innerhalb eines
256 kB-Bereichs oder innerhalb des gesamten 1 MB-Speichers der unterste 64
kB-Block adressiert werden soll.

Der Zugriff auf den eingestellten Common-Bereich wird durch das high
aktive Signal COMLH (U84, 74LS00 Pin 11 auf dem CPU-Board) angezeigt. Dieses
Signl wird ebenfalls an das PAL geführt (wie auch D1 von Port FBh. das
die Auswirkung von COMLH steuert), Durch D6 von Port FBh erfolgt schlielich
die Steuerung ob der G3s-Modus oder der Z180-Modus für die Adressierung des
RAMs zuständig ist. Das PAL-Assemblerlisting veranschaulicht alle diese
Steuerfunktionen.

Damit die Signale/CAS0-/CAS3 anstelle, der bisherigen Signale /CAS0-
/CAS3  an die RAMs gelangen, ist U43, 74LS125 zu entfernen. Die Signale
/CAS0 - /CAS3 des Adapter-Boards werden den RAMs über die Pins 3, 6, 11 und 8
der Fassung von U43 zugeführt. Die an diesen Pins liegenden Pull up-Wider-
stände R57-R60 sollten ausgelötet werden. Die Versorgung mit +5V und GND
kann von den Pins 14 und 7 derselben Fassung erfolgen. Und schließlich liefert
ihr Pin 9 auch noch das Signal /CAS für den Adapter.

Alle Signale, die dem Adapter-Board vom CPU-Board zugeführt werden
müssen, werden über den Stecker CN2 geführt; ebenso die Signale die das
Adapter-Board dem CPU-Board liefert. Nur die ursrünglichen Z80-Pin-Signale
laufen über den Sockel des Z80.

Der Einsatz eines Z180 bringt aber auch neue Probleme mit sich. Beim
Z8O wird der Sysemtakt extern erzeugt und der CPU über Pin 6 eingespeist.
Beim HD64180 und beim Z180 wird der Systemtakt, von der CPU geliefert. Dieser
Takt wird intern aus einem von außen zugeführten, doppelt so hohen Takt
hergeleitet.

Der G3s hat die  Möglichkeit (leider auch die Notwendigkeit), zwischen
einer hohen Frequenz und den normalen 1,77 MHz des TRS-80 umzuschalten.
Diese Umschaltung muß bereits mit dem doppelten Muttertakt erfolgen. Es muß
also zwischen 18.332 und 3,55 MHz umgeschaltet werden. Dadurch kann die CPU
nicht mehr mit einem normalen Quarz, an den Pins XT und EXT beschaltet
werden. Es müssen externe Oszillatorshaltungen benutzt werden. Der jeweils
selektierte Takt wird über einen Treiber (74LS125) an den Pin EXT der CPU
geschaltet. Die Auswahl des jeweiligen Taktes wird durch die Signale LO
(U41, 74LS74, Pin 9) und HI (U41, 74LS74 Pin 8) auf dem CPU-Board gesteuert.

Die bisherige Taktquelle im System wird durch Entfernen von U44,
74LS161 abgeschaltet. Damit der nun von der CPU gelieferte Systemtakt auch
auf dem CPU-Board verfügbar wird, müssen die Pins 5 und 6 von U39, 74LS125
aus der Fassung gebogen werden und die Pins 5 und 6 der Fassung miteinander
verbunden werden. Die Widerstände R51, R52 und R79 sollten entfernt werden.

Die für das ursprüngliche 256 kB-Banking des G3s verantwortlichen Bits
6 und 7 des Ports F9h (hier als Signale F96 und F97 bezeichnet) sind von den
Pins 14 und 13 von U88, 73LS139 zu beziehen.

Die vom Port FBh auf dem Adapter-Board zur Vervierfachung von Video-
RAM, Zeichensatz-RAM und HRG-RAM gelieferten Bits 2-5 (FB2-FB5) werden in
dieser Reihenfolge an folgende IC-Pins der Hauptplatine geführt:


U13', 73LS157, Pin 6
U13', 74LS177, Pin 3
BIG5 und BIG6, 6264, Pins 23 (diese Pins aus der Fassung biegen)
BTG5 und BIG6, 6264, Pins 2 (diese Pins sind bereits außerhalb der Fasung)


U13' ist ein mit den Pins 1, 8, 15 und 16 huckepack auf U13, 74LS157
gelötetes IC 74LS157. Die weitere Beschaltung dieses ICs gibt folgende
Abbilung wieder:

Abb. 1: 

U15' ist ebenfalls ein auf U15, 74LS157 mit den Pins 1, 8,  15 und 16
huckepack gelötetes weiteres IC 74S157.

Die Pins 15 und 16 von BIG1, 6845 sind aus der Fassung zu biegen und
mit U13' zu verdrahten.

Schließlich sind noch die Adressen A16 und A17 von CN2 den RAMs gemultiplext
zuzuführen. Das Multiplxen bsorgt ein auf U34, 74S157 wiederum mit
den Pins 1, 8, 15 und 16 huckepack gelöteter 74S157 (U34'), der an den Pins
13 und 14 mit A16 und A17 zu versorgen ist. Der Multiplex-Ausgang Pin 12
wird über 33 Ω mit den Pins 1 aller RAMs (32x 41236) verbunden.

Zur Vereinfachung des bis hierhin Gesagten sei das alles noch einmal in
einer Tabelle wiedergegeben:

Verbindunen von CN2 zum CPU-Board

Stecker CN2  CPU-Board
Pin  Signal  IC         Typ     Pin
-------------------------------------------------------------
1   +5V      U43        LS125   14 *   # huckepack gelötete
2   GMD      U43        LS125    7 *     ICs 74LS(S)157
3   /HI      U41        LS74     8       (s. Text und Abil-
4   /LO      U41        LS74     9       dungen
5   FB3      U13'       LS157    3 #
6   FB2      U13'       LS157    6 # 
7   FB5      BIG5/BIG6  6264     7
8   FB4      BIG5/BIG6  6264    23 (aus der Fassung biegen)
9   F96      U88        LS139   14
10  F97      U88        LS139   13     * U43 entfernen und
11  /CASO    U43        LS125    3 *     Sockel auslöten,
12  COMLH    U88        LS139   15       Signale von CN2 an
13  /CAS2    U43        LS125   11 *     die Lötpunkte der
14  /CAS3    U43        LS125    8 *     entsprechenden Pins
15  /CAS     U43        LS159    9 '     des Sockels von U43
16  /CAS1    U43        LS125    6 '     anlöten
17  A16      U33'       S157    13 #
18  A17      U34'       S157   	13 #

Außerdem sind auf dem CPU-Board noch folgende (z. T. beim Einbau des
4xG3s-Z80-Adapters schon durchgeführten) Änderungen nötig:

Die aus den Fassugnen gbogenen Pins 27 von BIG5 und BIG6 und U16' (alle,
74S157) sind mit Pin 5 von U57, 74S04 zu verbinden. Die Pins 27 von BIG5 und
BIG6 (6264), die beide außerhalb der Fassung hängen, werden mit Pin 1 von
U54, 74LS32 verbunden. Pin 27 von BIG4, 6264 wird mit Pin 3 von U54, 74LS32
verlötet.


Abb. 2:Pinout des Z180 und seines Sockels

Abb. 3: Auszüge aus der Schaltung


Die Listings der beiden PALs


PAL16L8
10.03.90  H. Bernhardt
Portdecodierung im GIIIs mit Z180 für zusätzl. Systemports

A0 A1 A2 A3 A4 A5 A6 A7 WR GND
RD OUTFB OUTFC OUTF3 IODC INF3 INFC IORQ INFB VCC

/INFB  = /IORQ * /RD * A7 * A6 *A5 * A4 *  A3 * /A2 +  A1 *A0
/OUTFB = /IORQ * /WR * A7 * A6 *A5 * A4 *  A3 * /A2 +  A1 *A0
/INFC  = /IORQ * /RD * A7 * A6 *A5 * A4 *  A3 *  A2 + /A1 *A0
/OUTFC = /IORQ * /WR * A7 * A6 *A5 * A4 *  A3 *  A2 + /A1 *A0
/INF3  = /IORQ * /RD * A7 * A6 *A5 * A4 * /A3 * /A2 +  A1 *A0
/OUTF3 = /IORQ * /WR * A7 * A6 *A5 * A4 * /A3 * /A2 +  A1 *A0
/IODC  = /IORQ *     * A7 * A6 *A5 * A4 * A3 *  /A2


PAL16L8
10.03.90  H. Bernhardt
RAM-Steuerung im GIIIs mit Z180

ZA16 ZA17 FB0 FB1 COMLH F96 F97 FB6 FB7 GND
CAS A17 CAS1 CAS2 CAS3 CAS0 ZA18 ZA19 A16 VCC

/ZA16  = /FB6 * /F96
       + /FB6 * COMLH
       +  FB& * ZA16
/ZA17  = /FB6 * /F97
       + /FB6 * COMLH
       +  FB6 * /ZA17
/CAS0  = /FB6 * /CAS  * /FB1  * /FB0
       + /FB6 * /CAS  * COMLH * /FB7
       +  FB6 * /CAS  * ZA19  * /ZA18
/CAS1  = /FB6 * /CAS  * /FB1  *  FB0  * /COMLH
       + /FB6 * /CAS  * /FB1  *  FB0  * FB7
       +  FB6 * /CAS  * /ZA19 *  ZA18
/CAS2  = /FB6 * /CAS  *  FB1  * /FB0  * /COMLH
       + /FB6 * /CAS  *  FB1  * /FB0  * FB7
       +  FB6 * /CAS  *  ZA19 * /ZA18
/CAS3  = /FB6 * /CAS  *  FB1  *  FB0  * /COMLH
       + /FB6 * /CAS  *  FB1  *  FB0  * FB7
       +  FB& * /CAS  *  ZA19 *  ZA18


Abb. 4: Layout (lötseitig gesehen)

Abb. 5: Bestückungsplan

Abb. 6: aufgebautes, angeschlossenes Board



Die Sorftware


Der Z180 verleitet mit seiner interessnten MMU (Memory Management Unit)
und seinem DMAC (Direct Memary Access Controller) geradezu zu Spielereien.
Der Leser sei versichert daß wir ihnen auch ausgiebig frnten. So ist es
z. B. kein Problem, den Bildschirm oder irgendeinen anderen physikalichen
Speicherabschnitt logisch gleich dreimal an verschiedenen Adressen im
64 kB-Fenster der CPU vorliegen zu haben. Hier soll aber ganz bierernst nur
vorgestellt werden, was an Änderngen im DOS und Unterstützungen für das DOS
prgrammiert wurde, um die Vorteile der neuen CPU nutzen zu können.

Zum Verständnis dessen, was sich nun eigentlich zum Besseren ändert,
möchten wir außer den im Hardware-Teil schon genannten Veröffentlichungen
noch auf ein Sonderheft des Club-80 (3) und einen Info-Artikel (4) hinweisen,
die zum Thema HD64180 erschienen sind. Diese CPU ist softwaremäßig identisch
mit dem Z180. Eine erneute Beschreibung der im wesentlichen gleichen
Eigenschaften erübrigt sich an dieser Stelle.

Es sind vier Programme, die für den Z180 geändert bzw. neu erstellt
wurden:

Patches in zwei verschiedenen Teilen von SYS0/SYS konfigurieren den Z180,
um seine Arbeitsgeschwindigkeit und seine MMU auf optimale Werte einzustellen
und um seinen DMAC dem System verfügbar zu machen.

SYS26/SYS ist zuständig, um die SYS-Files des DOS in Bank 0 des Speichers
zu puffern. Es wird nun nur noch angesprungen, wenn nicht der
Rechtspeil gedrückt wurde (was bedeuten würde, daß das DOS nicht gepuffert
werden soll). In SYS26 steht nun der DMA-Treiber aus dem neuen SYS0 bereits
zur Verfügung, was alle Blockladevorgänge beschleunigt. Die Pufferung der
DOS-Moduln benötigt jetzt nicht mehr das aufwendige Banking, das bisher
erforderlich war, denn der DMAC kann von überall her den vollen Adneßbereich
des Z180 überstreichen.

Eine Änderung in der SYS-Laderoutine, für den DOS-Kern ebenfalls in
SYS66 untergebracht, lädt nun die SYS-Programme bei einem DOS-Request mit
RST 28h per DMA entsprechend schneller und weniger speicheraufwendig. Daß im
Zuge dessen viel Platz in SYS26 frei wurde, der edleren Zwecken zur Verfügung
gestellt werden kann, sei nebenbei erwähnt. Zudem ist der besondere
Sektorpuffer 3A00h-3AFFh für die SYS-Moduln jetzt nicht mehr notwendig -
freier Speicher für andere Anwendungen.

Dann entstand ein Anwenderfile (bei uns TRAP/CMD geheißen), das hauptsächlich
Gerald Schröders Illegal-Trap-Programm in Bank 0 und Bank 1 an die, logische
Adresse 0000h patcht. Hier springt der Z180 nämlich hin, wenn er einen Befehl
antrifft, den er nicht kennt (für nähere Erleuterungen möchten wir auf Geralds
Artikel im Info Nr. 17 verweisen). Außerdem wird hier die Delay-Routine an
0060h verlangsamt, denn der Z180 arbeitet zu schnell, um mit dem alten
Verzögerungsprogramm noch die korrekten Wartezeiten zu erzielen.

Und schließlich zimmerten wir ein Utility-Programm namens SYSTEST/CMD für
den DOS-Tüftler (Listing 5). Wenn ein SYS-File, umgeschrieben wurde und
nach Murphy's Gesetz noch Fehler enthalten muß, kann es zunächst in der
Bank 0 gepuffert und (notfalls bei offenem Floppy-Türchen) von dort aus
getestet werden. Damit erübrigt sich gleichzeitig die Notendikeit, vor dem
Test erneut zu booten, um die Datei in die Bank 0 zu kriegen, von wo sie
beim gebankten DOS aufgerufen wird.

Alle Änderngen in SYS0 und SYS26 sowie die neuen Files TRAP/CMD und
SYSTEST/CMD sind in den Listings wiedergegeben. Weitere Teile, die sich in den
beiden SYS-Programmen nicht geändert haben, sind mit LIST OFF ausgespart
worden, um den Rahmen dieses Sonderhefts nicht zu sprengen. Dasselbe gilt
für TRAP/CMD, soweit es Geralds bereits bekanntes Trap-Programm betrifft.
Damit hat der Leser natürlich die Schwierigkeit, daß  unklar bleibt, wo die
Patches in den Files liegen sollen, und was sich in der Folge sonst noch
ändert. Sorry - da können wir nur anbieten, eine Systemdiskette bei Arnulf
anzufordern. Die Listings sollen lediglich den Umgang mit den neuen
Möglichkeiten des Z180 demonstrieren und die sich ergebenden Voreile besingen.

Es werden auch kleinere Teile der Listings unverständlich bleiben, weil
sie sich auf nicht gelistete Programmabschnitte beziehen. Es handelt sich
nämlich nicht um besondere Schöpfungen für dieses Sonderinfo, sondern um die
Sources für das geänderte DOS. Wenn etwa Labels auftauchen, die sonst nirgends
wiederzufinden sind, einfach darüber hinweglesen!

Die genannten Programme sind auch noch längst nicht der Weisheit letzter
Schluß. So ist es beispielsweise wünschenswert, einige Konfigurationen
des Z180 (WAIT-Zyklen, Refreshes, MMU, vielleicht noch mehr) bereits im
Boot-EPROM erledigen zu lassen. So weit sind wir jedoch selbst noch nicht.
Gegf. wird man in einem kommenden Clubinfo Weieres dazu vorfinden.

Soweit Befehle enthalten sind, die zwar der Z180, nicht aber der Z80 kennt,
sind sie mit ihren Hex-Entsprechungen als DB-(DEFB-)Statememts eingefügt.
ZEUS kennt sie nämlich bedauerlicherweise auch nicht. In einem Kommentar
erscheint dann jeweils der Befehl in Z180-Assembler.

Die Programme sind essentiell für das Betriebssystem. Ohne Betriebssystem
kein Computer. Daher wird unbedingt empfohlen, alles zunächst mit einer
Kopie der Systemdiskette auszuprobieren (für SYS29 kann aber auch SYSTEST
gefahren werden!). Erst, wenn sich die Kopie als funktionstüchtig erwiesen
hat, hat die alte Systemdisk asgedient!

Nun zu den Programmen im einzelnen:

SYS0/SYS ist die Seele des G3s. Es ist in seinem ersten Teil eine
Fortsetung von DOS/SYS. Hier ist die erste Modifikation für den Z180
untergebracht: Die Anzahl der WAIT-Zyklen für Speicher- und Portzugriffe wird
eingestellt, und zwar auf den schnellstmöglichen Wert. Solle er sich im
Einzelfall als Überforderung des Systems herausstellen, kann der Wert 00h
für den Akku mit DDE auf einen anderen Betrag gepatcht werden (XOR A hätte
den Akku ebenfalls gelöscht, jedoch ohne die MöglichXeit einer einfachen
Änderung). Danach wird die MMU des Z180 auf den Normalzustand des G3s
eingerichtet. So kann, etwa für einen DMA (s. u.), die Z180 Speicherkonfiguration
in aller Regel geschaltet werden, ohne daß sich etwas am Banking-Zustand ändert.

Die zusätzlichen Befehle (s. Listing 1) werden einfach in die (zuvor per
Disassembly gewonnene) Source eingefügt, das Programm neu assembliert.
Es besteht aus zwei Sektoren, die in die ersten beiden Sektoren von SYS0/SYS
gepatcht werden (das kann z. B. SUPERZAP).

Das Listing 2 zeigt ebenfalls einen Patch in SYS0. Anfangs wird getestet,
ob der Rechtspfeil während des Bootens gedrückt wurde. Ist das nicht der
Fall, möchte der User das DOS in Bank 0 des Computers puffern, um es
später ohne die Laufwerke verfügbar zu haben. Dieser Test war bisher in
SYS26 untergebracht. Es erschien uns überflüsig, SYS26 anzuspringen, wenn
es bei gedrücktem Rechtspfeil ohnehin gleich wieder verlassen wird.

Dann enthält das Listing einen Treiber für den DMAC des Z180. Er erwartet
beim Einsprung in HL die Anfangsadresse des zu transferierenden Blocks, in
DE die Zieladresse, in BC den Bytezähler. Bis hierher entspricht der Treiber
dem Z80-Befehl LDIR. Neu ist der Inhalt des Akkus, der in seinen beiden
Nibbles die Adressen A16-19 des Quell- und des Zielbereichs enthält.
So kann ein DMA auf das volle Megabyte des Z180-Adressraums zugreifen.

Die internen DMAC-Register SAROB (Kanal 0, Quelle, Bits 16-19) und
DAROB (Kanal 0, Ziel, Bits 16-19) werden nur in ihren unteren 4 Bits beachtet.
So war es zur Laufzeit- und Platzersparnis möglich, auf das Löschen der
oberen 4 Bits zu verzichten: Der Befehl RRD (Zeile 94) rotiert die hier
relevanten Bits 3-7 ins untere Nibble von DAROB, der folgende Befehl LD
(scrphys),A packt einfach den kompletten Akku mit seinem unwichig gewordenen
oberen Nibble nach SAROB.

In Zeile, 102 wird die G3s-MMU deaktiviert, indem in Port FBh das Bit 6
gesetzt wird (s. Hardware-Teil). Nur so kann der DMA-Treiber über das ganze
Megabte verfügen. Ansonsten könnte nur das 64 kB-Fenster, das gerade vom
G3s bearbeitet wurde, vom DMAC überstrichen werden. Also ist beim Einsprung
in die DMA-Routine unbedingt darauf zu achten, daß die MMU-Konfiguration des
Z180 mit der des G3s zumindest in wichtigen Speicherabschnitten übereinstimmt:
Der Treiber muß sich nach dem Umschalten selber wiederfinden können,
der Stack muß ebenfalls an derselben logischen Adresse vorliegen. Erst nach
dem Rückschaltbefehl (Zeile 111) ist Entwarnung gegeben.

Bei der Rückkehr aus dem Programm enthalten alle Register ihren alten
Wert, der gerettet wurde. Im Gegensatz dazu gibt der Befehl LDIR die Quell-
und Zielregister um den Betrag des Bytezählers erhöht zurück. BC selbst ist
dann 0000h. Dieser Service hätte mit in den Treiber eingebaut werden können,
der verfügbare Platz reichte jedoch nicht. Zudem haben beide Möglichkeiten
ihre Vor- und Nachteile.

An dieser Portion von SYS0 ist nur der filerelative Sektor 10h interessant.
Das ist der diskreltive Sektor 15h. Die Source gem. Listing 2 wird assembliert.
Von der so entstandenen CMD-Datei muß nun (mit SUPERZAP oder wie auch immer)
der erste Sektor nach SYS0 kopiert werden, und zwar in den eben bezeichneten
Sektor. Wichtig ist, daß dieser Sektor des CMD-Programms genau am relativen
Byte FFh aufhört, also ganz unten rechts. Danach, im nächsten Sektor, folgt
der Rest, der mit einem neuen Record-Header beginnt. Bis dorthin können
NOPs bzw. DW 0000h- oder DB 00h-Statements eingefügt werden. Um das Puzzle 
u erleichtern, folgt hier ein Sektor-Dump der den relativen Sektor 10h von
SYS0 wiedergibt:

file:  SYS0/SYS     drv: 0    frs: 0010h     drs: O015h
00:  01(C 0032 3E40 D3F9 FBC1 D1E1 C9E5 D5C5    2 >@
10:  3E01 F3D3 F9C3 0AF0 3A07 43F6 3032 8232  >        : C 02 2
20:  E60F FE04 2o11 3AF8 42CB 5F28 0A3A 4038         : B  ( :@8
30:  E640 3EFC CC02 4421 7F32 1180 4401 0B00   @>    D! 2  D
40:  EDB0 1180 4421 0042 CD24 4428 0BFE 1820       D! B $D(
50:  2B3E 0132 0743 180E EBCD 284C 201E 1162  +>  2 C   (L   b
60:  32D5 1198 31E9 2100 3011 AD4E 0100 023E  2   1 ! 0  N   >
70:  10CD BD35 E1F1 32F9 42C3 6744 F5CD C901     5  2 8 gD
80:  3E46 EF4F 564c 782F 5359 533A 300D 0170  >F OVLx/SYS:0  p
90:  BB35 22F0 35ED 53F3 35ED 43F6 35E5 21F5   5" 5 s 5 C 5 #
A0:  3577 ED67 32F2 3521 F735 C501 2708 F5D8  5w g2 5! 5
B0:  FBF5 F640 F3D3 FBED 9B01 3102 ED9B F1D3     @      1
C0:  FBF1 C1E1 C940 0200 0000 0000 0000 0000      @
D0:  0000 0000 0000 0000 0000 0000 0000 0000
E0:  0000 0000 0000 0000 0000 0000 0000 0000
F0:  0000 0000 0000 0000 0000 0000 0000 0000

Es ist ausreichend, das im Hex- und im ASCII-Teil unterstrichene Zählbyte
des Record-Headers (rel. Sektorbyte 8Fh) genau so zu zappen un den
Rest auszunullen. Dann dürfte nichts mehr schiefgehen. Voraussetzung ist,
daß das Zählbyte auch an dieser Stelle steht. Ansonsten muß es eben auf
andere Weise angepaßt werden, damit das letze Datenbyte des Sektors an der
sektorrelativn Stelle FFh zu liegen kommt.

Listing 3 behandelt ein paar Änderungen in SYS26. Dort wird, wie schon
erwähnt, das Puffern des DOS im Speicher veranlaßt. Gleichzeitig wird der
DOS-Kern gepatcht: Soll ein SYS-File mit RST 28h geladen werden, wird nicht
mehr die Floppy angeworfen. Statt dessen wird das Programm aus der Bank 0
geholt.

Dafür dient ein besonderes Minimal-DIR: Pro SYS-Modul enthält es zwei
Bytes. Das erste ist das MSB der Pufferadresse in Bank 0. Da das LSB immer
00h ist, da also jedes SYS-File am Anfang eines 256Byte-Blocks beginnt,
genügt das MSB. Das zweite Byte gibt die Länge des Files in Sektoren an.
Gepuffert werden nur die Programme SYS1-19. GDOS/SYS, IHHALT/SYS und
SYS0/SYS haben hier keine Bedeutung und bleiben deshalb auf der Floppy. Ihr
Platz im Mini-DIR ist mit Nonsene (GDOS) bzw. mit Nullen (INHALT und SYS0)
gefüllt.

Eine spezielle Laderotine für SYS-Programme liest dieses DIR und
transferiert dann die Sektoren ursprünglich nach 3A00h, einen besonderen
Sektorpuffer. Von dort wird das File sektorweise in den Overlay-Speicher des
DOS geladen und schließlich angesprungen.

Hier die Änderungen die die Vorteile des Z180 ausnutzen: Der DMAC benötigt
kein Banking, um Daten zu trasnsportieren. Die Unterprogramme, die das
DOS in den Speicher laden und es später beim Betrieb von dort wieder abholen,
konnten deshalb wesentlich verkürzt (und damit beschleunigt) werden.

Das UP putsys puffert die SYS-Files. Dazu wird zunächst der Teil von
INHALT/SYS ab 5200h in den Speicher geladen, der SYS-Programme enthält. Der
Platzbedarf von 0800h Bytes zerstört dabei nach Reset den Inhalt des
Anwenderspeichers. Daher wird (ab Label boot) zunächst dieser Bereich in die
Bank 1 gerettet um später restauriert zu werden. Dann wird das besondere SYS-DIR
im Block 3900h eingerichtet. Die ersten Bytes des Blocks müssen ausgenullt
werden, damit bei einem DOS-Request nicht versucht wird, INHALT oder SYS0
aus der Bank 0 zu holen; die Nullen sind Signalbytes für das Verbot.
Anschließend wird ab 4100h in Bank 0 das restliche DOS abgelegt.

Mit der Restauration des Anwenderspeichers und dem Transfer des SYS-DIR
an seine endgültige Adresse 4000h in Bank 0 endet dieser Teil von SYS26.

Der Patch im DOS-Kern, der SYS-Dateien aus der Bank 0 holt, ist anschließend 
gelistet. Der verfügbare Speicherlatz im residenten Teil von SYS0 (ab 3BE1h)
reicht dazu nicht aus. Ein notwendige Unterprogramm macht deshalb an der
Stelle 3738h weiter (was auch bisher schon so war). Dieses UP kann nun per
DMA auf aufwendiges Banking verzichten, das zuvor nötig war. Immerhin 13
Bytes wurden frei die Arbeitsgeschwindigkeit stieg enorm.

Das nächste Programm, das mit Listing 4 hier vorgestelt werden soll, ist
in dieser Form ein reines Anwender-File. Wegen seiner Wichtigkeit erscheint
es sinnvoll, es später einer SYS-Datei einzuverleiben, vielleicht
gleich SYS26. Es nimmt ein paar Patches im BASIC-Interpreter vor, die dem
Z180 gerecht werden.

Seine Arbeitsgeschwindigkeit ist deutlich höher als die des Z80, weil
viele Befehle weniger Taktzyklen beanspruchen. Dadurch beschleunigt sich die
Delay-Routine an 0060h bedenklich. Wartezeiten, die dort z.B. für den
Floppy-Controller abgetrödelt werden, sind nun zu kurz. Eine geringfügige
Änderung schafft Abhilfe, so daß die Verzögerungen fast genau mit der alten
Zeiten identisch werden:

In der alten Version wird mit einem JR NZ-Befehl in die Schleife
zurückverzeigt, wenn der Zähler BC noch nicht abgelaufen ist. Die neue Variante
durchläuft zuerst den Befehl RET Z, und zwar jedesmal. Hat der Zähler noch
etwas Stoff, geht es mit bedinungslosem JR zurück in die Schleife. Der
zusätzliche Return-Befehl, der bei jedem Schleifendurchlauf gelesen werden
muß, kostet die erwünschten Taktzyklen zur Verlangsamung.

Dies alles trifft freilich nur bei der langsameren Takt Fequenz von
1,77 MHz zu, die über Port FAh, Bit 6 gewählt werden kann. Alle kritischen
Verzögerungsschleilen des DOS werden jedoch, soweit uns bekannt, erst nach
dieser Taktumschaltung durchlaufen. Wo nicht, ist die verkürzte Laufzeit
durch den High-Speed-Takt des Z180-Boards immerhin noch erträglich zu
schnell.

Direkt an die Delay-Schleife schließt sich der NMI-Service an. Der
TRS-80 benutzt ihn als Reset-Ersatz. Beim G3s ist der NMI unbenutzt (hard-
warermäßig übrigens auch nicht zugänlich - die freien Tasten links oben und
unten in der Haupttastatur können mit dem NMI-Pin der CPU verdrahtet werden).
Unsere Serice-Rouine läßt einfach nur die Interrupts wieder zu. Damit können
z. B. die Dreitastenbefehle aktiviert werden, wenn man etwa jederzeit mit
dem Debugger den Speicher und die Reister im Auge haben möchte.

Hauptbestandteil dieses Programms ist jedoch Gerald Schröders Error-Trap-Routine.
Dorthin verzweigt der Z180, wenn ein ihm unbekannter Opcode
angetroffen wird. Auch hier möchten wir wieder auf schon erschienene
Erklärungen verweisen, um Wiederholungen zu vermeiden (Info Nr. 17).

Beim Einsprung am Label start wird der Beginn der Trap-Routine, nämlich
ein Sprung nach 1650h. nach 0000h ff. gezapt. Vor dem eigentlichen JP findet
sich ein NOP. Hier kann der User bei einem Trap-Interrupt auch etwas anderes
als diesen Sprung veranlassen. Mit F7h (RST 30h) an dieser Stelle wird z. B.
in den Debuger gesprungen. Besonders in der Experimentierphase, wenn der
Z180 noch neu ist, wird man das gelegentlich wollen.

Bei 1650h sind die BASIC-Befehle im Klartext abgelegt. Das Trap-Programm
überschreibt sie. Wer gerne in BASIC arbeitet, kann so natürlich nicht
verfahren. Eine andere Adresse muß her. In einem kommenden Info wird die
Lösung des Problems zu lesen sein.

In Bank 1 soll ebenfalls Geralds Trap-Programm verfügbar sein. Dort ist
ab 0000h Platz dafür, ein JP erübrigt sich. Diese neue Ladeadresse erfordert
die Relokation aller festen Adressen im Trap-Pogramm. Das beginnt mit Zeile
188 im Listing. Der Vorgang ist etwas verzwickt. Wir möchten aber darauf
verzichten, ihn über die Kommentare im Listing hinaus zu erleutern. Dies
kann kein Lehrbuch über Z80-Assembler sein). Alle kritischen Adressen wurden
mit einem Label versehen, addr1-addr15. addr1 ist im Listing sichtbar, die
übrigen nicht. Diese Labels finden sich in der Tabelle addrtab wieder.

Nur ein Detail soll beleuchtet werden. Weil der Leser u. U. nicht
gleich RAMDISK (s. u.) über JP 4405h abfahren möchte: Beim Sprung nach 4405h
wird über den Requestcode 63h nach SYS1 verzweigt. Mit, diesem code im Akku
(ACHTUNG: mit etlichen anderen nicht!) wird als erstes der Stack neu
eingerichtet, weil dabei eine Rückkehr zum Aufrufer nicht stattfinden soll.
Für den CALL dma und die PUSHes und POPs im DMA-Treiber genügt ein
vorübergehender Stack an beliebiger Stelle. Er wird hier (zeile 199,) kurz
und schnell unter die Trap-Routine gelegt.

Bei einem anderen Aussprung aus TRAP/CMD, ganz besonders mit RET, muß
zuvor der Original-Stack unbedingt gerettet und nachher restauriert werden.
Das geht mit dem Strickmuster nach dem auch die Zeilen 192 und 189/190 (in
dieser Reihenfolge!) funkionieren. Das hätten wir unter Dreingabe von ein
paar Bytes und Mikrosekunden natürlich auch hier so machen können, aber
dieser schlitzohrigere Weg war halt gar zu verlockend.

Nachdem nun die Trap-Routine auch nach Bank 1 tranferiert ist, wird zuletzt
die RAM-Disk des G3s aktiviert. Dieser Programmbestandteil wäre verzichbar.
Da wir aber immer mit der RAM-Disk arbeiten, kann das getrost gleich mit
erledigt weren. Wenn nein: Unbedingt die Aussprungs-Bedingungen
beachten (Stack, s. o.). Übrigens ist der ursprüngliche Name des Proramms
MEMDISK/CMD. Hier handelt es sich um eine geänderte Version.

SYSTEST transferiert ein CMD-Programm, das als SYS-File des DOS dienen
soll, in die Bank 0, von wo die SYS-Dateien mit RST 28h aufgerufen werden.
Prinzipiell geht das mit jeder Datei, in der Regel wird es sich jedoch
um neue Versionen eines echten DOS-Moduls handeln.

Es beginnt gem. Listing 5 mit der Prüfung, ob das DOS überhaupt schon in
Bank 0 gepuffert ist. Das ist die Voraussetzung, weil sonst die neue Datei
nicht mit RST 28h erreichbar wäre. Sollte das noch nicht geschehen sein,
wird SYS26 (s. d.) mit FCh im Akku zuerst aufgerufen, um das DOS zu banken.
Zum Test dient ein Lückenfüller-NOP, das bei der geänderten SYS-Laderoutine
an der Stelle 4C0Bh stehen muß.

Das eigentliche Arbeitsprogrogramm klärt nun zunächst, was für ein CMD-File
in we1ches SYS-Programm kopiert werden soll. Diese Angaben können jedoch
schon beim Aufruf gemacht werden, denn die Befehlssyntax ist

SYSTEST<,FILSPEC<,SYSNR>>.

Wenn der zweite oder beide Befehlsparameter weggelassen werden, wird nach
ihnen gefragt. Dabei wird FILESPEC in der üblichen Weise. z. B. auch  mit
Laufwerksnummer, eingegeben. SYSNR ist nur eine Dezimzahl für SYSx/SYS.

In der Bank 0 befinden sich nur die Files SYS1-29. Das Programm prüft
daher auch, ob mit SYSNR eine zulässige Datei benannt wurde. Außerdem darf
die Testdatei höchstens so lang sein wie die Zieldatei in Bank 0. Sonst
würde das dahinter liegende SYS-File übesschrieben werden. In diesem Falle,
wie überhaupt bei jedem denkbaren Fehler, bricht das Pragramm mit einer
DOS-Fehlermeldung ab. Dies geschieht mit einem Sprung nach DOSERR (4409h),
wo der Stack neu eingerichtet wird. Daher durfte getrost ignoriert werden,
ob gerade ein PUSH oder CALL den Stack verbogen hat.

Auch hier sollen allzu weitschweifige Erklärungen des Programms vermieden
werden. Die Kommentare mögen genügen. Für die ausgiebigen Aufrufe etlicher
DOS-Routinen möchten wir auf Grossers "DOS-Buch" (5) verweisen, ohne das
wir es übrigens wohl auch nicht geschafft hätten. Es sei nur darauf
hingewiesen, daß wieder der DMA benutzt werden konnte, und daß ein komfortabler
Befehl des Z180. MLT ww (3), das Umrechnen einer Dezimal- in eine Binärzahl
erleichterte (zeile 31/32).

In der kommenden Zeit, liegt eine interessante Aufgabe in der weiteren
Umgestaltung des Systems auf den Z180 hin. Wir würden uns freuen, wenn auch
die Nachbauer des Z180-Boards gelegentlich mit Software im Club-Info vertreten
wären. Vorschlag: Auch und gerade die RAM-Disk kann von der neuen CPU
profitieren.


Literatur:

(1) Bernhardt, Sopp, Sonder-Info "Dein GIIIs, die 4 unbekannten Wesen",
Michelbach,/Bilz 1986

(2) Bernhardt,  "512k-RAM-Addressierung mit flexibler MMU", Club-Info 18,
Michelbach/Bilz 1987

(3) Bernhardt, Schröder Sonder-Info "HD64180". Gschlachtenbretzingen 1989

(4) Schröder, "Z80, HD6418 und Illegals", Club-Info 17, Michelbach/Bilz 1987

(5) Grosser, "Das DOS-Buch", Aachen 1985

		00001 ;Listing 1:	Patch in SYS0/SYS, rel. Sektor 00h:
		00002 ;SYS0/SYS	konfiguriert den Z180 für G-DOS
		00003 ;FRS 006	(hier nicht interessierende Teile sind mit LIST OFF
		00004 ;DRS 05h	ausgespart - erkennbar an den springenden Zeilennummern)

		00035
4010 3E00	00036 m4d10	LD	A,00h			;A <- 00: Memory: 0 WAITs, I/O: 1 WAIT
4012 ED		00037		DB	0edh,39h,32h		;OUT0(32h),A
4015 3E83	00038		LD	A,83h			;RFSH alle 80 Zyklen 2 Zyklen lang
4017 ED		00039		DB	0edh,39h,36h		;OUT0(36h),A
4D1A 21624E	00040		LD	HL,mmutab		;Tabelle der MMU-Werte
4010 013803	00041		LD	BC,endtab-mmutab'256+38h ;3 Werte ab Port 38
4020 ED 	00042		DB	0edh,93h		;001110 (Werte ausgeben)

		00208
		00209 ;Tabelle zum Einrichten der MMU des 2180
4E62 10		00210 mmutab	DB	10h			;Common 1 ab	1.1000
4E63 10		00211		DB	10h			;Bank-Area ab	1.4000
4E64 E4		00212		DB	0e4h			;hierfür die logischen Adressen
		00213 endtab
00000 Fehler

		00001 ;Listing 2: Patch in SYS0/SYS im relativen Sektor 10h:
		00002 ;SYS0/SYS	stellt einen DMA-Treiber zur Verfügung
		00003 ;FRS 10h	(unteressierende Teile sind mit LIST OFF
		00004 ;DRS 15h	ausgespart - erkennbar an springenden Zeilennummern)
		00005

		00037 ;Test auf Rechtspfeil: DOS banken oder nicht? (früher in SYS26/SYS)
3229 3A4038	00038		LD	A,(m3840)		;Tastatur Steuerzeichen
322C E640	00039		AND	40h			;Rechtspfeil gedrückt? (nein: DOS banken)
322E 3EFC	00040		LD	A,0fch			;Requestcode für SYS26/SYS
3230 CCO244	00041		CALL	Zm4402			;mit OST 28h SYS26 aufrufen (DOS banken)
3233 217F32 	00042 m322c	LD	HL,m3275		;Filename 'OVL4/SYS'

		00081
		00082 ;Unterprogr. für DMA: HL = LSW Quelle, DE = LSW Ziel, BC = Bytezähler,
		00083 ;A Bit 0-3 = MSB der Quelle, A Bit 4-7 . MSB des Ziels
		00084 ;(858 . most significant byte, A16-19, obere 4 Bits der Adresse,
		00085 ; LSW . less word, A0-15, untere 16 '   )
		00086
3588		00087		ORG	35bbh
3588 22E035	00088 dma	LD	(srclog),HL		;Quellbereich log. LSW	x.HL
35BE ED53F335	00089		LD	(dstlog),DE		;Zielbereich log. LSW x.DE
35C2 E043F635	00090		LD	(bytcnt),BC		;Bytezähler	0.BC
35C6 E5		00091		PUSH	HL
35C7 210535	00092		LD	HL,dstphys		;Zielbereich  Phys. MSB	Ah.DE
35CA 77		00093		LD	(HL),A			;MSB setzen (016-19: Bit 4-7)
35C8 ED67	00094		RRD				;Nibbles rotieren (A16-19: Bit 0-3)
35CD 32F235	00095		LD	(srcphys),A		;Quellbereich phys. MSB	Al.HL
3500 21F735	00096		LD	HL,tabend		;Beginn der DMA-Wertetabelle
3503 C5		00097		PUSH	8C
3504 012708	00098		LD	BC,0827h		;8 Werte ab Port 27 abwärts
3507 F5		00099		PUSH	AF
3508 DBFB	00100		IN	A,(0fbh)		;Systembyte 2
35DA F5		00101		PUSH	AF			;retten
3508 F640	00102		OR	40h			;MMU des Z180 freigeben
3500 F3		00103		DI
350E D3FB	00104		OUT	(Ofbh),A
		00105 ;		OTDMR	;DMAC aufsetzen
35E0 ED		00106		DB	0edh,9bh		;(Hex-Entsprechung des Befehls)
35E2 013102	00107		LD	BC,0231h		;2 Werte ab Port 31 abwärts
		00108 ;		OTDMR				;Rest aufsetzen u. DMA abschießen
35E5 ED		00109		DB	0edh,9bh
35E7 F1		00110		POP	AF			;altes Systembyte 2
35E8 D3FB	00111		OUT	(0fbh),A

35EA F1		00112		POP	AF
35E8 C1		00113		POP	8C
35EC E1		00114		POP	HL
35ED C9		00115		RET
		00116
		00117 ;Wertetabelle für den DMA-Controller (fallende Reihenfolge für OTDMR)
35EE 40		00118		DB	40h	;30, DSTAT: Kanal 0, Zustand 'scharf'
35EF 02		00119		DB	02h	;31, DMODE: Speicher zu Speicher, Burst-Modus
35F0 0000	00120 srclog	DW	0000h	;20/1, SAROL/H: Duelladresse LSW x.####
35F2 00		00121 srcphys	DB	00h	;22, SAR0B: MS8	#.xxxx
35F3 0000	00122 dstlog	DW	0000h	;23/4, DAR0L/H: Zieladresse LSW	x.#1114
35F5 00		00123 dstphys	DB	00h	;25, DAROB: MSB	#.xxxx
35F6 0000	00124 bytcnt	DW	0000h	;26/7, BCR0L/H: Bytezähler für die Programmlänge
35F7		00125 tabend	EQU	$-1	;Ende der Tab., womit der Zeiger HL geladen wird
00000 Fehler

		00001 ;Listing 3: Patch in SYS26/SYS:
		00002 ;SYS26/SYS  neue Routine zum Puffern und Laden von SYS-Files
		00003 ;in Bank 0 des User-RAMs
		00004 ;(hier nicht interessierende Teile sind mit LIST OFF
		00005 ;ausgespart - erkennbar an den springenden Zeilennummern)
		00006
 
35BB		00012 dma	EQU	35bbh	;Adresse des DMA-Treibers

		00331
		00332 ;UP zum Übertragen von SYS-Files in die Bank 0
		00333 ;		E:	HL = Adresse RAM-DIR-Eintrag
		00334 ;			D  = Länge des Files in Sektoren
		00335 ;			E  = Adreß-MSB des Files in der Bank 0
		00336
4F1C E5		00337 putsys	PUSH	HL 			;39xx, DIR-Eintrag des akt. SYS-Files
4F1D D5		00338		PUSH	DE'			;E . MSB des SYS-Files, D . Länge in Skt.
4F1E C5		00339		PUSH	BC
4F1F F5		00340		PUSH	AF
4F20 73		00341		LD	(HL),E			;MSB der Zieladresse ins SYS-DIR
4F21 23		00342		INC	HL			;nächste Stelle
4F22 72		00343		LD	(HL),D			;Zählbyte eintragen
4F23 210042	00344		LD	HL,m4200		;Sektorpuffer
4F26 010001	00345		LD	BC,0100h		;Länge 1 Skt.
4F29 53		00346		LD	D,E			;DE <- Zieladresse (MSB) des Sektors
4F2A 59		00347		LD	E,C			;(LSB immer =00)
4F28 3E01	00348		LD	A,01h			;von Bank 1 nach Bank 0
4F2D CDB835	00349		CALL	dma			;Block übertragen
4F30 F1		00350		POP	AF
4F31 C1		00351		POP	BC
4F32 D1		00352		POP	DE
4F33 E1		00353 		POP	HL
4F34 FB		00354		EI
4F35 C9		00355		RET
		00356
		00357 ;Einsprung bei Boot: RAM-Inhalt retten, SYS-Files in der Bank 0 puffern
4F36 210052	00358 boot	LD	HL,m5200		;Beginn des zu überschreibenden Bereichs
4F39 110008	00359		LD	DE,0800h		;Zwischenpuffer dafür in Bank 1
4F3C 42		00360		LD	B,D			;BC <- 0800, zu überschreibender Bereich
4F30 48		00361		LD	C,E
4F3E ES		00362		PUSH	HL
4F3F D5		00363		PUSH	DE
4F40 3E11	00364		LD	A,11h			;von Bank 1 nach Bank 1
4F42 CDB835	00365		CALL	dma			;RAM-Inhalt retten
4F45 ED739141 	00366		LD	(m4f10),SP		;alten Stach retten
4F49 CDCB4E	00367		CALL	m4f55			;DIR-Sektoren mit SYS-Entries laden
4F4C 210039	00368		LD	HL,m3900		;vorläufiger SYS-DIR-Puffer
4F4F 110139	00369		LD	DE,m3900+1		;zum Ausnullen vorbereiten

4052 78		00370		LD	A,E			;A <- 01, Zähler für 1 Durchgang
4053 32074F	00371		LD	(filelen),A		;dort ablegen
4056 0E06	00372		LD	C,06h			;Zähler 6 Bytes (f3 = 00 seit m4f55)
4058 75		00373		LD	(HL),L			;1. Byte des SYS-DIR-Puffers ausnullen
4059 EDB0	00374		LDIR				;Rest ausnullen (hier schneller als DMA)
409 1E41 	00375		LD	E,41h			;ab Page 4100 die SYS-Files puffern

4040 El		00407		POP	HL			;Adresse des gepufferten RAM-Inhalts
4041 D1		00408		POP	DE			;seine frühere Ladeadresse
4042 44		00409		LD	B,H			;BC <- 0800h, Blocklänge (C=00 seit LDIR)
4043 3E11	00410		LD	4,11h			;von Bank 1 nach Bank 1
4045 CDBB35	00411		CALL	dma			;RAM-Inhalt ab 5200h restaurieren
4048 210039	00412		LD	HL,m3900		;Puffer für SYS-DIR
4FAB 110040	00413		LD	DE,m4000		;endgültige Adresse dafür in Bank 0
4FAE 0601	00414		LD	8,01h			;Länge 256 Bytes (C = 00)
4080 AF		00415		XOR	A			;A - 00: Bank 0 -> Bank 0, 'kein Fehler'
4081 C3BB35	00416		JP	dma			;Block übertragen und zurück ins DOS
		00417
		00418 ;Patch im DOS-Kern: Einsprung bei DOS-Request mit RST 28h
0303		00419 offs4	EAU	$-4be1h		;Abstand zur Ladeadresse
4084 3E40	00420 m4be1	LD	A,34000/256	;DIR des gebankten DOS (Adreß-MSB)
4066 323037	00421		LD	(addrmsb-offs3),A	;in Laderoutine patchen
4F69 CD3837	00422		CALL	m3738-offs3		;in den Sektorpuffer übertragen
408C 2642	00423		LD	H,m4200/256		;Sektorpuffer (MS8)
4FBE 341743	00424		LD	4,(4317h)		;SYS-Kenner
40C1 07		00425		RLCA				;2 (wegen 2 Bytes pro Eintrag)
40C2 6F		00426		LD	L,A			;als LSB des Zeigers laden
4FC3 7E		00427		LD	A,(HL)			;Adreß-MSB des SYS-Files in Bank 0
4FC4 323037	00428		LD	(addrmsb-offs3),A	;in die Laderoutine patchen
4FC7 23		00429		INC	HL			;auf Längenbyte stellen
4008 7E		00430		LD	A,(HL)			;laden
40C9 87		00431		OR	A			;= 00? (dann INHALT/SYS oder SYSO/SYS)
4FCA 2815	00432		JR	Z,m4c0e			;Fehler, falls ja (nicht vorhanden)
4FCC 213837	00433		LD	HL,m3738-offs3		;modifizierte Sektor-Laderoutine
4000 22604C	00434		LD	(4c6dh),HL		;in SYSO patchen
4002 CD2B4C	00435		CALL	4c2bh			;SYS-File laden
4005 221E4C	00436		LD	(4c1eh),HL		;Startadresse des SYS-Files dort patchen
4008 213644	00437		LD	HL,4436h		;alte Sektor-Laderoutine
4008 22604C	00438		LD	(4c6dh),HL		;restaurieren
4FDE 00		00439		NOP				;Füller bis zur alten Fortsetzung
40E1		00440 m4c0e	EQU	§+2
		00441
		00442 ;neue Laderoutine für SYS-Files
18A7		00443 offs3	EQU	$-3738h
4FDF E5		00444 m3738	PUSH	HL
40E0 D5		00445		PUSH	DE
40E1 C5		00446		PUSH	BC
4FE2 210000	00447		LD	HL,0000h		;Duellblock in Bank 0
40E4		00448 addrmsb 	EQU	$-1			;MSB wird jeweils gepatcht
40E5 7C		00449		LD	A,H			;Adreß-MSB
40E6 3C		00450		INC	A			;100h Bytes weiter
4FE7 323037	00451		LD	(addrmsb-offs3),A	;MSB für nächsten Block patchen
4FEA 3E10	00452		LD	4,10h			;aus Bank 0 nach Bank 1
4FEC 110042	00453		LD	DE,m4200		;Sektorpuffer
4FEF 010001	00454		LD	BC,0100h		;Sektorlänge
4002 CDBB35	00455		CALL	dma			;Block übertragen
4005 Cl		00456		POP	BC
4006 D1		00457		POP	DE
4007 EI		00458		POP	HL
4008 AF		00459		XOR	A			;Flag 'kein Fehler'
4009 C9		00460		RET
00000 Fehler

		00001 ;Listing 4:	Einige Änderungen für den Z180 im BASIC-Interpreter
		00002 ;TRAP/CMD		Hauptsächlich Delay und Illegal-TRAP-Routine
		00003 ;			(Gerals Schröders TRAP-Routine idt mit LIST-OFF aus-
		00004 ;			gespart, nachzulesen Club-Info Nr. 17, nur ihr
		00005 ;			GIIIs-spezifischer Anfang ist gelistet
		00006
0000		00007 target1	EQU	0000h			;Zieladresse der Trap-Routine in Bank 1
1650		00008 target0	EQU	1650h			;dto. in Bank 0, vorläufig im BASIC Bereich
35BB		00009 dma	EQU	35BB			;Aresse des DMA-Treibers
		00010
5200		00011		ORG	5200h
		00012
		00013 ;Trap-Einsprung für Adresse 9
5200 00		00014 lowmem	NOP				;Platz für eventl. F7 (RST 30, Debugger)
5201 C35016	00015		JR	target0			;Einsprung bei Trap-Interrupt
		00016
		00017 ;Einsprung der Warteschleife und NMI-Routineab Adresse 0060
5204 0B		00018 delay	DEC	BC			;(alter Teil der Delay-Routine
5205 78		00019		LD	A,B			;bleibt unverändert)
5206 B1		00020		OR	C
5207 C8		00025		Ret	Ẑ			;neu: wird immer bearbeitet (Verrzögerung)
5208 18FA	00022		JR	delay			;jetzt Laufzeit etwa wie Z80
		00023
520A FB		00024 nmi	EI				;NMI: Interrupt zulassen
520B C9		00025		RET
		00026
		00027 ;Fehlerbehandlung bzw. Illegal-Simulation nach einem Trap-Interrupt
		00028 ;vorläufige Version: kein anderer RST 00h außer TRAP berücksichtigt!
388C		00029 offs	EQU	$-target0		;Abstand zur Arbeitsadresse
520C F3		00030 trap	DI				;Interrupt aus
520D F5		00031		PUSH	AF			;Akku und Flags retten
520E DBFA	00032		IN	A,(0fah)		;System-Byte 1
5210 32FA16	00033		LD	(fsbuff-offs),A		;puffern
5211		00034 addr1	EQU	$-2
5213 E6DF	00035		AND	0dfh			;evtl. Schreibschutz aufheben
5215 03FA	00036		OUT	(0fah),A		;System-Byte neu ausgeben
		00171
52C7 DBFA	00172 start	IN	A,(0fah)		;System-Byte 1
52C9 E6DF	00173		AND	0dfh			;evtl. Schreibschutz aufheben
52CB F3		00174		DI
52CC D3FA	00175		OUT	(0fah),A		;neu ausgeben
52CE 240052	00176		LD	HL,(lowmem)		;Code für Adresse 0000h
52D1		00177		LD	(0000h),HL		;am Zielort ablegen
52D4 1A0202	00178		LD	HL,(lowmem+2)		;Fortsetzung, insgesamt 4 Byte
52D7 220200	00179		LD	(0003h),HL
52DA 52DD	00180		LD	HL,delay		;neue Verzögerungs-Routine
52DD 116000	00181		LD	DE,0060h		;Zieladresse
52E0 010B00	00182		LD	BC,trap-delay		;Länge
52E3 EDB0	00183		LDIR				;(wenige Bytes) LDIR schneller als DMA
52E5 115016	00184		LD	DE,target0		;Zieladresse (HL bereits auf Quelle trap)
52E8 018800	00185		LD	BC,atart-trap		;Länge
52EB 3E01	00186		LD	A,01h			;von Bank1 nach Bank0
52ED CDBB35	00187		CAll	dma			;Block übertragen (schneller als LDIR)
52F0 060F	00188		LD	B,ebdtab-addrtab/2	;Anzahl zu relozierender Abressen
52F2 311E53	00189 adrlop	LD	SP,addrtab		;Stack auf Adressentabelle
52F3		00190 spbuff	EQU	$-2
52F5 E1		00191		POP	HL			;eine Adresse abholen
52F6 ED73F352	00192		LD	(spbuf),SP		;Tabelle als Stack retten
52FA F9		00193		LD	SP,HL			;dortige Adresse = Stack
52FB E1		00194		POP	HL			;dortiges Word abholen
52FC ED52	00195		SBC	HL,DE			;auf neue Basisadresse umrechnen
52FE E5		00196		PUSF	HL			;neues Woed ablegen
52FF 10F1	00197		DJNZ	addrlop			;bis alle Adressen bearbeitet
5301 210C52	00198		LD	HL,trap			;Adresse der Trap-Routine

5304 F9		00199		LD	SP,HL			;unterhalb neuer Stack
5305 110000	00200		LD	DE,target1		;Zieladresse in Bank 1
5308 018800	00201		LD	BC,start-trap		;Länge der TRAP-Routine
5308 3E11	00202		LD	4,11h			;von Bank 1 nach Bank 1
5300 CDCB35	00203		CALL	dma			;TRAP-Routine nach Bank 1 verladen
5310 211653	00204		LD	HL,ramdisk		;Aufruf der RAM-Disk (kann entfallen)
5313 C30544	00205		JR	4405h			;als DOS-Befehl ausführen und ENDE
		00206
5316 52		00207 ramdisk	DM	'RAMDISK',Odh	;Nage des RAM-Disk-Programms, CR
		00208
		00209 ;Tabelle der zu relozierenden Adressen in der TRAF-Routine
531E 1152	00210 addrtab	DW	addr1,addr2,addr3,addr4,addr5,addr6,addr7,addr8
532E 7352	00211		DW	addr9,addr10,addr11,addr12,addr13,addr14,addr15
		00212 endtab
00000 Fehler

		00001 ;Listing 5:	Ein geändertes SYS-File soll vor dem endgültigen Gebrauch
		00002 ;SYSTEST/CMD	in Bank 0 gepuffert und von dort aus getestet werden.
		00003
6000		00004		ORG	6000h
		00005
3588		00006 dma	EAU	35bbh			;DMA-Treiber
		00007
6000 34084C	00008 start	LD	4,(4c0bh)		;bei depuffertem DOS steht dort 00
6003 87		00009		OR	A			;ist das DOS in Bank 0 schon gepuffert?
6004 2807	00010		JR	Z,go_baby		;alles klar, falls ja
6006 05		00011		PUSH	HL			;Befehlszeiger retten
6007 3EFC	00012		LD	A,Ofch			;Requestcode für SYS26: DOS erst bunkern
6009 CD0244	00013		CALL	4402h			;dort steht RST 28h für den DOS-Request
600C El		00014		POP	HL			;Befehlszeiger
600D CDD54C	00015 go_baby	CALL	4cd5h			;HL auf nächsten Befehlsparameter stellen
6010 2006	00016		JR	NZ,makefcb		;falls etwas folgt
6012	11AF60	00017		LD	DE,filespc		;Text 'Name ..."
6015 CD9560	00018		CALL	getinpt			;ausgeben, Dateinamen einlesen
6018 11E060	00019 makefcb	LD	DE,fcb			;FCB-Adresse
6018 CD1C44	00020		CALL	441ch			;Dateinamen in den FCB übertragen
601E 02044	00021		CALL	442011			;FCB eröffnen
6021 206D	00022		JR	NZ,errexit		;falls Fehler aufgetreten
6023 CDD54C	00023		CALL	4cd5h			;HL auf nächsten Befehlsparameter stellen
6026 2006	00024		JR	NZ,getsys		;falls etwas folgt
6028 11C960	00025		LD	DE,sysnmbr		;Text 'SYS-File ..."
6028 CD9560	00026		CALL	getinpt			;ausgeben, SYS-Nr. einlesen
602E CD9F60	00027 getsys	CALL	getciph			;1. Ziffer binär umwandeln
5031 78	00028	LD		AA				;Binärziffer
6032 2800	00029		JR	Z,putsys		;falls Eingabe beendet (SYS1-9)
6034 0E0A	00030		LD	C,Oah			;Faktor 10d für zweistellige Zahlen

		00031 ;	MLT	BC				;BC = B *  C: B <- 00, C <- 10*B
6036 ED		00032		DB	0edh,4ch		;Hex-Entsprechung des Befehls
6038 CD9F60	00033		CALL	getciph			;2. Ziffer einlesen (muß letzte sein)
603B 2053	00034		JR	NZ,errexit		;falls Eingabe noch nicht beendet
603D 78		00035		LD	6,5			;neue Ziffer (binär)
603E 81		00036		ADD	A,C			;+ 10mal 1. Ziffer
603F 3C		00037 putsys	INC	A			;+2, weil GDOS und INHALT keine Nr. haben
6040 3C		00038		INC	A
6041 FE03	00039		CP	03h			;SYS1? ('kleinste' erlaubte SYS-Datei)
6043 3849	00040		JR	C,illnmbr		;Fehler: Eingabe von SYSO
6045 FE20	00041		CP	1fh+1			;SY529? ('höchste' erlaubte SYS-Datei)
6047 3045	00042		JR	NC,illnmbr		;falls Quatsch wie etwa SYS4711
6049 07		00043		RLCA				;'2, weil 2 Bytes pro Eintrag im SYS-DIR
6044 08		00044		EX	AF,AF'			;retten
6046 210040	00045		LD	HL,4000h		;dort in Bank 0 das SYS-DIR
604E 110080	00046		LD	DE,8000h		;Puffer dafür in Bank 1

6051 05		00047		PUSH	DE			;für später
6052 45		00048		LD	B,L			;BC <- 0040h = 64d, Länge des SYS-DIR
6053 4C		00049		LD	C,H
6054 3E10	00050		LD	A,10h			;von Bank 0 nach Bank 1
6056 CDBB35	00051		CALL	dma			;SYS-DIR in den Puffer übertragen
6059 08		00052		EX	AF,AF'			;aufbereitete SYS-Nr.
6058 5F		00053		LD	E,A			;DE <- Adresse des Eintrags im SYS-DIR
6058 1A		00054		LD	A,(DE)			;MSB der Adresse des SYS-Files in Bank 0
605C 328560	00055		LD	(sysaddr),A		;dort ablegen
605F 13		00056		INC	DE			;auf Längenbyte (Blockzähler) stellen
6060 14		00057		LD	A,(DE)			;laden
6061	5F	00058		LD	E,A			;DE <- Länge des SYS-Files (LSB)
6062 55		00059		LD	D,L			;MSB . 00 (max. 35 Sektoren bei SYS6)
6063 2AEC60	00060		LD	HL,(fcb+0ch)		;2. u. 1. EOF-Byte, gibt Länge in Skt. an
6066 7D		00061		LD	A,L			;Zähler für zu ladende Skt. (LS8 genügt)
6067 3C		00062		INC	A			;0.1, weil ab 0 gezählt, Cy lösch. wg. SSC
6068 47		00063		LD	B,A			;B als Zähler aufsetzen
6069 328860	00064		LD	(bytecnt),A		;als DMA-Bytezähler (MSB) patchen
606C E052	00065		SBC	HL,DE			;beide Filelängen vergleichen
606E 3E3B	00066		LD	A,3bh			;Fehlercode 'unzureich. Speicherplatz'
6070 301E	00067		JR	NC,errexit		;falls Testfile zu lang
6072 EI		00068		POP	HL			;Puffer ab 8000h in Bank 1
6073 11E060	00069		LD	DE,fcb			;Zeiger auf den FCB
6076 22E360	00070 ldloop	LD	(fcb+03h),HL		;Pufferadresse in den FCB schreiben
6079 24		00071		INC	H			;Pufferzeiger 256 Bytes weiterstellen
6074 CD3644	00072		CALL	4436h			;einen Sektor einlesen
607D 2011	00073		JR	NZ,errexit		;falls ein Fehler auftrat
607F 10F5	00074		DJNZ	ldloop			;bis alle Sektoren eingelesen sind
6081 2680	00075		LD	H,8000h/256		;HL <- Puffer 8000h in Bank 1 (LSB . 00)
6083 110000	00076		LD	DE,0000h		;Zieladresse in Bank 0 (LSB immer 00)
6085		00077 sysaddr	ECU	$-1			;MSB der SYS-Adresse in Bank 0
6086 010000	00078		LD	BC,0000h		;Bytezähler (LSB immer 00)
6088		00079 bytecnt	ECU	$-1			;MSB wird gepatcht
6089 3E01	00080		LD	A,01h			;von Bank 1 nach Bank 0
6088 C38835	00081		JP	dma			;neues SYS-File speichern und ENDE
00082
608E 3E29	00083 illnmbr	LD	A,29h			;Fehlercode 'unzul. log. Dateinummer'
6090 E67F	00084 errexit	AND	7fh			;NZ-Bedingung (Fehler), keine Rückkehr
6092 C30944	03085		JP	4409h			;Fehlermeldung ausgeben und ENDE
		00086
6095 EB		00087 getinpt	EX	DE,HL			;HL - Zeiger auf Text
6096 CD6744	00088		CALL	4467h			;Text anzeigen
6099 0620	00089		LD	8,206			;max. 32d Zeichen (sehr reichlich)
6098 EB		00090		EX	DE,HL			;HL - DOS-Eingabepuffer für Eingabe
609C C34000	00091		JP	0040h			;Eingabe einlesen und zurück
00092
609F 7E		00093 getciph	LD	A,(HL)			;Zeichen laden
60A0 FE30	00094		CP	'0'			;kleinste erlaubte Ziffer?
6082 38EA	00095		JR	C,illnmbr		;Fehler, falls kleiner
6044 FE3A	00096		CP	'9'4.1			;größte erlaubte Ziffer?
6046 30E6	00097		JR	NC,illnmbr		;Fehler, falls größer
6088 E60F	00098		AND	Ofh			;ASCII -) binär
60AA 47		00099		LD	8,A			;Eingabe binär puffern
6048 23		00100		INC	HL			;Befehlszeiger nachstellen
60AC C3D54C	00101		JP	4cd5h			;nächsten Befehlsparam. holen und zurück
		00102
		00103 ;verschiedene Texte und Puffer
60AF 4E		00104 filespc DM 'Name des Testprogramms? ',0eh,03h	;Text, Churs., EOS
60C9	53	00105 sysnsbr DM 'SYS-File-Nr.',09h,'(1-29)? ',0eh,03h	;dto. mit TAB
		00106 fcb						;Puffer für FCB
		00107
6000		00108		END	start
00000 Fehler


Anhang

Probleme mit den Illegals

Geralds Trap-Programm ist eine wertvolle Hilfe, dennoch kein Allheilmittel.
Von den vielen denkbaren Illegals, die im Code-Muster des Z80 stecken, sind
längst nicht alle bereits entschlüsselt und dokumentiert. Die Trap-Routine
müßte daher bei jeder neuen Entdeckung aktualisiert werden.

Und der Z180 benutzt selber für seine neuen Befehle solche ehemals
weißen Stellen in der Code-Matrix des Z80. Glücklicherweise beschieden sich
seine Designer mit solchen Codes, die mit dem Switch-Byte EDh beginnen, so
daß ein notwendiges Debugging verdächtiger Programme in Grenzen bleibt.
Nämlich auch Illegals mit EDh werden schon irgendetwas beim Z80 bewirken,
was auch immer. Die Illegal-Trap-Routine würde in diesem Falle überhaupt
nicht angesprungen, denn es wäre für den Z180 ja ein sinnvoller Befehl.

Einer dieser beiden Gründe wird es wohl sein, weshalb nach der Umrüstung
des G3s auf den Z180 ausgerechnet mit ZEUS/CMD zahlreiche Abstürze
auftraten. Aber vielleicht wurde auch Geralds Programm falsch abgetippt.
Egal - es mußte etwas geschehen, denn mit ZEUS steht und fällt die Soft-Seite
des ganzen Unternehnens:

DSMBLR ist ein Disassembler, der gottlob keine Illegals akzeptiert, wie
es z. B. ZEUS durchaus tut. Wenn man daher ein Programm disassembliert, das
Illegals enthält, zuckt DSMBLR ratlos die Achseln und setzt DM-(DEFM-)
Statements, wo er in seinem Vorrat keinen Z80-Befehl findet (DSMBLR und ZEUS
behandeln DB und DM gleich, soweit es sich um einzelne Bytes handelt).

So haben wir ZEUS ohne jegliches Screening disassembliert und nach DMs
gesucht. An vier Stellen wurden wir fündig (Listing 6). In einem gesonderten
File, mit dem wir seit jeher ZEUS patchen (ZAPZEUS/CMD, Listing 7), wurden
Simulationen der Illegals programmiert, in ZEUS selbst CALLs nach dort
gepatcht.

ZAPZEUS (für diesen Zweck genügen die gelisteten Teile) kann so abgetippt
und auf Papier assembliert werden. Die Bestandteile bis Zeile 46 werden
etwa mit Hilfe von FED/CMD, mitten in ZEUS gezapt. Was dahinter liegt,
muß im letzten Sektor von ZEUS angehängt werden. Der Ende-String
(02-02-xy-xx) wird als neuer Record-Header (01-nn-yy-xx) geändert. Das
Anhängsel-Programm bringt seinen eigenen Ende-String mit. Dafür ist es
wichtig, daß seine Einsprungsadresse (END addr) die von ZEUS sein muß
(s. Listing).

Ob damit alles erledigt ist, muß die zukünftige Praxis zeigen. Ohne ein
Screening-File für DSMBLR werden nämlich Texte und Tabellen wie Programmcode
disassembliert. So ergeben sich Verschiebungen im "Programm"-Ablauf, die
etwa ein Illegal-Switch-Byte wie einen harmlosen Bestandteil eines
Sprungbefehls (Adresse, Distanz) erscheinen lassen können. Da das aber nur
auftreten kann, wenn ein Illegal direkt an einen reinen Datenblock grenzt,
darf man mit Recht auf Erfolg hoffen.

Auch das Gegenteil wäre eine mögliche Fehlerquelle: Eine Tabelle, die
ohne Screening ja nicht als solche behandelt wird, enthält ein verdächtiges
Byte. Der Zufall will es, daß der Inhalt der Tabelle wie sinnvoller
Programmcode aussieht. Ein dort gepatchter CALL würde die Tabelle verfälschen.
Wir können nur raten, in solchen Fällen die betreffenden Stellen ganz
besonders sorgfältig zu untersuchen ...


... und unbedingt das Ergebnis zur Veröffentlichung an Jens-80 Neueder
zu schicken!

00001 ;Listing 6:	Illegals in ZEUS/CMD
00002 ;ZEUS/CMD	(hier nicht interessierende Teile sind mit LIST 0FF
00003 ;	ausgespart - erkennbar an den springenden Zeilennummern)
00004 
52E7 DD		00305		DM	Oddh		;DD 7D:'
52E8	7D	00306		LD	A,L		;LD A,LX
52E9	FE28	00307		CP	'+'
		00308 
5809 CB		00694		DM	Ocbh		;CB 31 06 01:
5800 310601	00695		LD	SP,e0106	;SLIA C - LD 8,01
		00696 
5045 C8		00731		DM	Ocbh		;C3 31 06 01:
5846 310601	00732		LD	SP,m0106	;SLIA C - LD 8,01
		00733 
64E9 C3		00700		DM	Ocbh		;CB 37:
6AEA 37		00701		SCF			;SLIA A
		00702
00000 Fehler

		00001 ;Listing 7:	Illegal-Trap direkt in ZEUS/CMD
		00002 ;ZAPZEUS/CMD	(hier nicht interessierende Teile sind mit LIST 0FF
		00003 ;ausgespart - erkennbar an den springenden Zeilennummern)
		00034
52E7		00035		ORG	52e7h		;dort Illegal LD A,LX
52E7 CD2830	00036		CALL	Id_a_lx		;simulieren
		00037
5809		00038		ORG	5b09h		;dort Illegal SLIA C
5809 CD3330	00039		CALL	slia_c		;simulieren
		00040
5845		00041		ORG	5b45h		;dort Illegal SLIA C
5845 CD3330	00042		CALL	slia_c		;simulieren
		00043
6AE9		00044		ORG	6ae9h		;dort Illegal SLIA A
6AE9 37		00045		SCF			;Cy für Bit 0 setzen
6AEA 17		00046		RLA			;rotieren
		00076
3000		00077		ORG	3000h		;wo es nicht stört
		00106
3028 DDE5	00107 ld_a_lx	PUSH	IX		;auf den Stack
302A E3		00108		EX	(SP),HL		;HL retten, HL - IX
3028 7D		00109		LD	A,L		;A - LX
302C E3		00110		EX	(SP),HL		;HL und IX restaurieren
302D DDE1	00111		POP	IX
302F FEH	00112		CP	2bh		;überschriebenen Befehl nachholen
3031 1805	00113		JR	return		;zurück zur Fortsetzung
		00114
3033 CB21	00115 slia_c	SLA	C		;C shiften
3035 OC		00116		INC	C		;Bit 0 setzen
3036 0601	00117		LD	8,01h		;überschriebenen Befehl nachholen
		00118
3038 E3		00119 return	EX	(SP),HL		;HL - RET-Adresse
3039 23		00120		INC	HL		;ein Byte später
3030 E3		00121		EX	(SP),HL		;zurücktauschen
3038 C9		00122		RET			;an die neue Adresse zurückkehren
		00123
5312		00124		END	5312h		;hier Einsprung in ZEUS
00000 Fehler

